package devcontainer

import (
	"strconv"

	"code.gitea.io/gitea/models/repo"
	"code.gitea.io/gitea/modules/log"
	web_module "code.gitea.io/gitea/modules/web"
	Result "code.gitea.io/gitea/routers/entity"
	context "code.gitea.io/gitea/services/context"
	gitea_web_context "code.gitea.io/gitea/services/context"
	devcontainer_service "code.gitea.io/gitea/services/devcontainer"
	"code.gitea.io/gitea/services/forms"
)

// CreateRepoDevcontainer 创建 某用户在某仓库的 DevContainer
//
// POST /api/devcontainer
// 请求体参数：
// -- repoId: 需要为哪个仓库创建 DevContainer
// -- sshPublicKeyList: 列表，填入用户希望临时使用的SSH会话加密公钥
// 注意：必须携带 用户登录凭证
func CreateRepoDevcontainer(ctx *context.Context) {

	// 1. 检查用户登录状态，若未登录则返回未授权错误
	if ctx == nil || ctx.Doer == nil {
		Result.RespUnauthorizedFailure.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 2. 检查表单校验规则是否失败
	if ctx.HasError() {
		// POST Binding 表单正则表达式校验失败，返回 API 错误信息
		failedToValidateFormData := &Result.ResultType{
			Code: Result.RespFailedIllegalParams.Code,
			Msg:  Result.RespFailedIllegalParams.Msg,
			Data: map[string]string{
				"ErrorMsg": ctx.GetErrMsg(),
			},
		}
		failedToValidateFormData.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 3. 解析 repoId
	form := web_module.GetForm(ctx).(*forms.CreateRepoDevcontainerForm)
	repoId, err := strconv.ParseInt(form.RepoId, 10, 64)
	if err != nil || repoId <= 0 {
		failedToParseRepoId := Result.ResultType{
			Code: Result.RespFailedIllegalParams.Code,
			Msg:  Result.RespFailedIllegalParams.Msg,
			Data: map[string]string{
				// fix nullptr dereference of `err.Error()` when repoId == 0
				"ErrorMsg": "repoId 必须是正数",
			},
		}
		failedToParseRepoId.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 4. 调用 API Service 层创建 DevContainer
	repo, err := repo.GetRepositoryByID(ctx, repoId)
	if err != nil {
		errCreateDevcontainer := Result.ResultType{
			Code: Result.RespFailedCreateDevcontainer.Code,
			Msg:  Result.RespFailedCreateDevcontainer.Msg,
			Data: map[string]string{
				"ErrorMsg": "repo not found",
			},
		}
		errCreateDevcontainer.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}
	devcontainer_service.CreateDevcontainerConfiguration(repo, ctx.Doer)

	err = devcontainer_service.CreateDevcontainerAPIService(ctx, repo, ctx.Doer, form.SSHPublicKeyList, false)
	if err != nil {
		errCreateDevcontainer := Result.ResultType{
			Code: Result.RespFailedCreateDevcontainer.Code,
			Msg:  Result.RespFailedCreateDevcontainer.Msg,
			Data: map[string]string{
				"ErrorMsg": err.Error(),
			},
		}
		errCreateDevcontainer.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 4. 创建 DevContainer 成功，直接返回
	Result.RespSuccess.RespondJson2HttpResponseWriter(ctx.Resp)
}

// GetDevcontainer 查找某用户在某仓库的 DevContainer
//
// GET /api/devcontainer
// 请求体参数：
// -- repoId: 需要为哪个仓库创建 DevContainer
// -- wait: 是否等待 DevContainer 就绪（默认为 false 直接返回“未就绪”，否则阻塞等待）
// -- UserPublicKey
// 注意：必须携带 用户登录凭证
func GetDevcontainer(ctx *gitea_web_context.Context) {
	// 1. 检查用户登录状态，若未登录则返回未授权错误
	if ctx == nil || ctx.Doer == nil {
		Result.RespUnauthorizedFailure.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 2. 取得参数
	repoIdStr := ctx.FormString("repoId")
	UserPublicKey := ctx.FormString("userPublicKey")
	log.Info(UserPublicKey)
	repoId, err := strconv.ParseInt(repoIdStr, 10, 64)
	if err != nil || repoId <= 0 {
		Result.RespFailedIllegalParams.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}
	repoDevcontainerVO, err := devcontainer_service.OpenDevcontainerAPIService(ctx, ctx.Doer.ID, repoId)
	if err != nil {
		failureGetDevcontainer := Result.ResultType{
			Code: Result.RespFailedOpenDevcontainer.Code,
			Msg:  Result.RespFailedOpenDevcontainer.Msg,
			Data: map[string]any{
				"ErrorMsg": err.Error(),
			},
		}
		failureGetDevcontainer.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 4. 封装返回成功信息
	successGetDevContainer := Result.ResultType{
		Code: Result.RespSuccess.Code,
		Msg:  Result.RespSuccess.Msg,
		Data: repoDevcontainerVO,
	}
	successGetDevContainer.RespondJson2HttpResponseWriter(ctx.Resp)
}

// DeleteRepoDevcontainer 删除某仓库的 DevContainer
//
// DELETE /api/devcontainer
// 请求体参数：
// -- repoId: 需要为哪个仓库创建 DevContainer
// 注意：必须携带 用户登录凭证
func DeleteRepoDevcontainer(ctx *gitea_web_context.Context) {
	// 1. 检查用户登录状态，若未登录则返回未授权错误
	if ctx == nil || ctx.Doer == nil {
		Result.RespUnauthorizedFailure.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 2. 取得参数 repoId
	repoIdStr := ctx.FormString("repoId")
	repoId, err := strconv.ParseInt(repoIdStr, 10, 64)
	if err != nil || repoId <= 0 {
		Result.RespFailedIllegalParams.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	err = devcontainer_service.DeleteDevContainer(ctx, ctx.Doer.ID, repoId)
	if err != nil {
		failureDeleteDevcontainer := Result.ResultType{
			Code: Result.RespFailedDeleteDevcontainer.Code,
			Msg:  Result.RespFailedDeleteDevcontainer.Msg,
			Data: map[string]any{
				"ErrorMsg": err.Error(),
			},
		}
		failureDeleteDevcontainer.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 4. 删除成功，返回提示信息
	Result.RespSuccess.RespondJson2HttpResponseWriter(ctx.Resp)
}

// ListUserDevcontainers 枚举已登录用户所有的 DevContainers
//
//		GET /api/devcontainer/user
//		请求输入参数：
//	 - page: 当前第几页（默认第1页），从1开始计数
//	 - pageSize: 每页记录数（默认值 setting.UI.Admin.DevContainersPagingNum）
func ListUserDevcontainers(ctx *gitea_web_context.Context) {

	// 1. 检查用户登录状态，若未登录则返回未授权错误
	if ctx.Doer == nil {
		Result.RespUnauthorizedFailure.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 2. 查询数据库 当前登录用户拥有写入权限的仓库
	userPage := ctx.FormInt("page")
	if userPage <= 0 {
		userPage = 1
	}
	userPageSize := ctx.FormInt("page_size")
	if userPageSize <= 0 || userPageSize > 50 {
		userPageSize = 50
	}
	userDevcontainersVO, err := devcontainer_service.GetDevcontainersList(ctx, ctx.Doer, userPage, userPageSize)

	if err != nil {
		resultFailed2ListUserDevcontainerList := Result.ResultType{
			Code: Result.RespFailedListUserDevcontainers.Code,
			Msg:  Result.RespFailedListUserDevcontainers.Msg,
			Data: map[string]string{
				"ErrorMsg": err.Error(),
			},
		}
		resultFailed2ListUserDevcontainerList.RespondJson2HttpResponseWriter(ctx.Resp)
		return
	}

	// 3. 封装VO
	resultListUserDevcontainersVO := Result.ResultType{
		Code: Result.RespSuccess.Code,
		Msg:  Result.RespSuccess.Msg,
		Data: userDevcontainersVO,
	}

	// 4. JSON序列化，写入输出流
	responseWriter := ctx.Resp
	resultListUserDevcontainersVO.RespondJson2HttpResponseWriter(responseWriter)
}
